package br.com.pontoclass.primes;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;

import javax.imageio.ImageIO;

import br.com.pontoclass.patterns.PrimeNumberListener;
import br.com.pontoclass.primes.util.MathLogicUtil;


public class SpiralCanvasPrimeNumberListener implements PrimeNumberListener {
    
    private static final int INITIAL_Y = 128;
    
    private static final int INITIAL_X = 4096;

    private static final int DEFAULT_HEIGHT = 6240;

    private static final int DEFAULT_WIDTH = 8192;

    private static final int BASE_PRIME = 9973;

    private String base;
    
    private boolean flag = true;
    
    private int xFrom = INITIAL_X;
    
    private BufferedImage image;

    private String imagePath;

    private Graphics2D g;

    private int oldValue;
    
    public SpiralCanvasPrimeNumberListener(String base, String imagePath) {
        this.base = base;
        this.imagePath = imagePath;
        image = new BufferedImage(DEFAULT_WIDTH, DEFAULT_HEIGHT, BufferedImage.TYPE_BYTE_GRAY);
        g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        g.setBackground(Color.WHITE);
        g.fillRect(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT);
        g.setColor(Color.BLACK);
//        BasicStroke bs = new BasicStroke(2);
//        g.setStroke(bs);
    }
    
    @Override
    public void onAddPrime(BigInteger prime) {
        prime = MathLogicUtil.convertFrom(new BigInteger(base), prime);
        if(prime.intValue() <= BASE_PRIME) {
            if(flag) {
                paintUp(prime.intValue(), g); 
            } else {
                paintDown(prime.intValue(), g);
            }
            flag = !flag;
            if(prime.intValue() == BASE_PRIME) {
                writeImage();
            }
        }
    }

    private void writeImage() {
        File outputfile = new File(imagePath);
        try {
            ImageIO.write(image, "jpg", outputfile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void paintDown(int value, Graphics g) {
        xFrom += (oldValue - value); 
        g.drawArc(xFrom, INITIAL_Y, value, value, 180, 180 + (value - oldValue));
    }

    private void paintUp(int value, Graphics g) {
        g.drawArc(xFrom, INITIAL_Y, value, value, 0, 180);
        oldValue = value;
    }
}